home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 79 / maccd 79.iso / multimedial / GL Tron / Source / gltron / png_texture.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-13  |  4.0 KB  |  158 lines  |  [TEXT/CWIE]

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #ifndef WIN32
  5. #include <unistd.h>
  6. #endif
  7.  
  8. #include "png_texture.h"
  9.  
  10. #define ERR_PREFIX "[load_png_texture] "
  11.  
  12. #include <png.h>
  13.  
  14. FILE *f;
  15.  
  16. void user_read_data(png_structp png_ptr,
  17.             png_bytep data, png_size_t length) {
  18.   fread(data, 1, length, f);
  19. }
  20.  
  21. png_texture* load_png_texture(char *filename) {
  22.   int i;
  23.   int bpc, color_type, zsize;
  24.  
  25.   png_texture *tex;
  26.   /* the following is defined in <png.h> */
  27.   png_uint_32 x, y;
  28.   png_structp png_ptr;
  29.   png_infop info_ptr;
  30.   png_byte **row_pointers;
  31.   
  32.   f = fopen(filename, "rb");
  33.   if(f == NULL) {
  34.     fprintf(stderr, ERR_PREFIX "can't open file %s\n", filename);
  35.     return NULL;
  36.   }
  37.  
  38.   png_ptr = png_create_read_struct
  39.     (PNG_LIBPNG_VER_STRING, 0, 0, 0);
  40.  
  41.   if (!png_ptr)
  42.     return NULL;
  43.  
  44.   info_ptr = png_create_info_struct(png_ptr);
  45.   if (!info_ptr){
  46.     png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
  47.     return NULL;
  48.   }
  49.  
  50.   /*  png_init_io(png_ptr, f);
  51.       fprintf(stderr, "png, after init io \n");  */
  52.  
  53.   /* I need to do this, otherwise it crashes on win32 */
  54.   png_set_read_fn(png_ptr, 0, user_read_data);
  55.   /* fprintf(stderr, "png, after init user_read_data\n"); */
  56.  
  57.   png_read_info(png_ptr, info_ptr);
  58.   /* fprintf(stderr, "png, after read info \n"); */
  59.   png_get_IHDR(png_ptr, info_ptr, &x, &y, &bpc, &color_type, 0, 0, 0);
  60.  
  61.   if(color_type != PNG_COLOR_TYPE_RGB &&
  62.      color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
  63.     png_destroy_read_struct(&png_ptr, &info_ptr, 0);
  64.     fprintf(stderr, ERR_PREFIX "wrong png_color_type\n");
  65.     fclose(f);
  66.     return NULL;
  67.   }
  68.  
  69.   if(bpc != 8) {
  70.     png_destroy_read_struct(&png_ptr, &info_ptr, 0);
  71.     fprintf(stderr, ERR_PREFIX "wrong bitdepth: %d\n", bpc);
  72.     fclose(f);
  73.     return NULL;
  74.   }
  75.  
  76.   switch(color_type) {
  77.   case PNG_COLOR_TYPE_RGB: zsize = 3; break;
  78.   case PNG_COLOR_TYPE_RGB_ALPHA: zsize = 4; break;
  79.   default: 
  80.     fprintf(stderr, "unknown png color type\n");
  81.     return NULL;
  82.   }
  83.  
  84.   tex = (png_texture*) malloc(sizeof(png_texture));
  85.   tex->data = malloc(x * y * zsize);
  86.   tex->width = x;
  87.   tex->height = y;
  88.   tex->channels = zsize;
  89.   
  90.     /* get pointers */
  91.   row_pointers = (png_byte**) malloc(y * sizeof(png_byte*));
  92.   for(i = 0; i < y; i++)
  93.     row_pointers[i] = tex->data + (y - i - 1) 
  94.       * zsize * x;
  95.  
  96.   png_read_image(png_ptr, row_pointers);
  97.   png_destroy_read_struct(&png_ptr, &info_ptr, 0);
  98.  
  99.   free(row_pointers);
  100.   fclose(f);
  101.   return tex;
  102. }
  103.  
  104. void unload_png_texture(png_texture *tex) {
  105.   free(tex->data);
  106.   free(tex);
  107. }
  108.  
  109. #define TARGET(X, Y, I) (mip->data + I + mip->channels * (X + Y * mip->width))
  110. #define SOURCE(X, Y, I) (source->data + I + \
  111.              source->channels * (X + Y * source->width))
  112.  
  113. png_texture* mipmap_png_texture(png_texture *source, int level, 
  114.             int clamp_u, int clamp_v) {
  115.   png_texture *mip;
  116.   int i;
  117.   int x, y;
  118.   int fx, fy;
  119.  
  120.   if(level != 1) return NULL;
  121.   mip = (png_texture*) malloc(sizeof(png_texture));
  122.   mip->channels = source->channels;
  123.   fx = (source->width > 1) ? 2 : 1;
  124.   fy = (source->height > 1) ? 2 : 1;
  125.               
  126.   mip->width = source->width / fx;
  127.   mip->height = source->height / fy;
  128.   mip->data = (unsigned char*) malloc(mip->width * mip->height *
  129.                       mip->channels);
  130.  
  131.   /* simple linear filtering */
  132.   for(i = 0; i < mip->channels; i++) {
  133.     for(y = 0; y < mip->height; y++) {
  134.       for(x = 0; x < mip->width; x++) {
  135.     /*
  136.     *( TARGET(x, y, i) ) = ( *( SOURCE(x * fx, y * fy, i) )  +
  137.                  *( SOURCE((x + 1) * fx, (y + 1) * fy, i) ) +
  138.                  *( SOURCE((x + 1) * fx, y * fy, i) ) + 
  139.                  *( SOURCE(x * fx, (y + 1) * fy, i) ) ) / 4;
  140.                  */
  141.     int sx, sy, xoff, yoff;
  142.     sx = fx * x;
  143.     sy = fy * y;
  144.     xoff = fx - 1;
  145.     yoff = fy - 1;
  146.  
  147.     *( mip->data + i + mip->channels * ( x + y * mip->width ) ) =
  148.       ( *( source->data + i + source->channels * ( sx + sy * source->width) ) +
  149.         *( source->data + i + source->channels * ( sx + xoff + sy * source->width) ) +
  150.         *( source->data + i + source->channels * ( sx + xoff + (sy + yoff) * source->width) ) +
  151.         *( source->data + i + source->channels * ( sx + (sy + yoff) * source->width) ) ) / 4;
  152.  
  153.       }
  154.     }
  155.   }
  156.   return mip;
  157. }
  158.